﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;

namespace KM.Framework.Utility
{
    public partial class SharpZipHelper
    {
        private static void GetDirAndFileList(DirectoryInfo dir, List<FileInfo> fileList)
        {
            DirectoryInfo[] dirs = dir.GetDirectories();
            fileList.AddRange(dir.GetFiles());

            foreach (var dirTemp in dirs)
            {
                GetDirAndFileList(dirTemp, fileList);
            }
        }

        public static void CompressDirectory(string dirFullPath, string zipFileFullPath, bool isContainsRootDir, Action<int> compressPercentChanged = null)
        {
            if (!Directory.Exists(dirFullPath))
                throw new ApplicationException("文件不存在或者已经被删除!");
            DirectoryInfo dir = new DirectoryInfo(dirFullPath);
            List<FileInfo> fileList = new List<FileInfo>();

            GetDirAndFileList(dir, fileList);

            using (ZipOutputStream zipedStream = new ZipOutputStream(File.Create(zipFileFullPath)))
            {
                for (int i = 0; i < fileList.Count; i++)
                {
                    var file = fileList[i];
                    string entryName = string.Empty;
                    if (isContainsRootDir)
                        entryName = string.Format("{0}{1}", dir.Name, file.FullName.Substring(dirFullPath.Length));
                    else
                        entryName = file.FullName.Substring(dirFullPath.Length + 1);

                    ZipEntry entry = new ZipEntry(entryName);
                    using (FileStream fs = file.OpenRead())
                    {
                        byte[] buffer = new byte[fs.Length];
                        fs.Read(buffer, 0, buffer.Length);
                        zipedStream.PutNextEntry(entry);
                        zipedStream.Write(buffer, 0, buffer.Length);
                    }

                    if (compressPercentChanged != null)
                    {
                        int percent = (int)((double)(i + 1) / fileList.Count * 100);
                        compressPercentChanged(percent);
                    }
                }
                zipedStream.Finish();
            }
        }

        public static void DecompressFile(string zipFileFullPath, string dirFullPath)
        {
            if (!File.Exists(zipFileFullPath))
                throw new ApplicationException("文件不存在或者已经被删除!");

            using (FileStream fs = File.OpenRead(zipFileFullPath))
            {
                ZipInputStream zipInputStream = new ZipInputStream(fs);

                while (true)
                {
                    ZipEntry entry = zipInputStream.GetNextEntry();
                    if (entry == null)
                        break;

                    if (entry.IsDirectory)
                    {
                        string dirName = Path.Combine(dirFullPath, Path.GetDirectoryName(entry.Name));
                        if (!Directory.Exists(dirName))
                            Directory.CreateDirectory(dirName);
                    }
                    else if (entry.IsFile)
                    {
                        string dirName = Path.Combine(dirFullPath, Path.GetDirectoryName(entry.Name));
                        if (!Directory.Exists(dirName))
                            Directory.CreateDirectory(dirName);

                        string fileName = Path.Combine(dirName, Path.GetFileName(entry.Name));

                        if (File.Exists(fileName))
                            throw new ApplicationException(string.Format("解压异常：文件【{0}】已存在!", fileName));

                        byte[] bytesTemp = new byte[entry.Size];
                        int readLength = zipInputStream.Read(bytesTemp, 0, bytesTemp.Length);

                        if (readLength != entry.Size)
                            throw new ApplicationException(string.Format("解压异常：readLength != entry.Size!"));

                        if (bytesTemp.Length > 0)
                            File.WriteAllBytes(fileName, bytesTemp);
                        else
                            File.Create(fileName);//创建空文件
                    }
                }
                zipInputStream.Close();
            }
        }
    }
}
